Skip to content

[FEA] Add support for scalar column views in AST expressions and JIT execution - #23615

Open
lamarrr wants to merge 2 commits into
NVIDIA:mainfrom
lamarrr:literal-opt
Open

[FEA] Add support for scalar column views in AST expressions and JIT execution#23615
lamarrr wants to merge 2 commits into
NVIDIA:mainfrom
lamarrr:literal-opt

Conversation

@lamarrr

@lamarrr lamarrr commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Description

This PR allows AST literals used by the JIT executor to reference a preconstructed
scalar_column_view. Previously, every scalar literal was materialized as a one-row column on
every JIT transform call. That setup cost dominates workloads that repeatedly evaluate expressions
over wide tables or small row batches.

The change:

  • Extends cudf::ast::literal to hold either an existing cudf::scalar or a non-owning
    scalar_column_view.
  • Updates AST literal type and validity handling for both representations.
  • Updates the row-IR converter to pass prepared scalar-column views directly to cudf::transform
    while retaining ownership of columns materialized for the existing scalar path.
  • Adds ast_jit_wide_table to TRANSFORM_NVBENCH, covering:
    • table width;
    • rows per transform call;
    • total rows;
    • expression depth;
    • ast, jit, and jit-opt executors.

In the benchmark, jit uses AST literals backed by cudf::scalar, while jit-opt uses
equivalent literals backed by preconstructed scalar_column_view objects.

A literal constructed from a scalar_column_view is non-owning. The referenced one-row column must
remain alive for the lifetime of the literal and its evaluation.

Performance

Measured on an NVIDIA RTX A6000 with 262,144 total rows and a table width of one. Expression depth
and rows per transform call were swept from 1 to 128 and 512 to 131,072, respectively.

Expression depth jit-opt speedup over jit
1 1.79-1.95x
2 2.90-2.95x
4 4.82-4.98x
8 5.83-7.08x
16 11.24-12.01x
32 17.04-19.71x
64 19.74-22.66x
128 24.28-27.24x

At expression depth 128:

  • 512 rows per call improved from 2,363.69 ms to 86.76 ms (27.24x).
  • 131,072 rows per call improved from 9.30 ms to 0.383 ms (24.28x).

A matched Nsight Systems profile at depth 16 and 1,024 rows per call showed that both paths execute
the same 256 JIT transform kernels with effectively identical transform-kernel time (0.601 ms versus
0.599 ms). Reusing scalar-column views removed 4,096 scalar copy kernels and 4,096 async copies,
reducing the profiled benchmark range from 189.9 ms to 21.1 ms (8.98x).

Checklist

  • I am familiar with the Contributing Guidelines.
  • New or existing tests cover these changes.
  • The documentation is up to date with these changes.

- Introduced `scalar_column_view` handling in the `literal` class.
- Updated `row_ir` to accommodate both scalar columns and scalar column views.
- Enhanced input handling in JIT execution to support new scalar types.
- Added a new benchmark for wide table transformations in NVBench.
@lamarrr
lamarrr requested review from a team as code owners August 10, 2026 23:29
@github-actions github-actions Bot added libcudf Affects libcudf (C++/CUDA) code. CMake CMake build issue labels Aug 10, 2026
@lamarrr lamarrr changed the title Add support for scalar column views in AST expressions and JIT execution [FEA] Add support for scalar column views in AST expressions and JIT execution Aug 10, 2026
@lamarrr lamarrr removed libcudf Affects libcudf (C++/CUDA) code. CMake CMake build issue labels Aug 10, 2026
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 88c873a5-f890-48b0-afdb-cde919d47d05

📥 Commits

Reviewing files that changed from the base of the PR and between 9c734e4 and 2d2085d.

📒 Files selected for processing (1)
  • cpp/benchmarks/transform/transform_widetable.cpp
🚧 Files skipped from review as they are similar to previous changes (1)
  • cpp/benchmarks/transform/transform_widetable.cpp

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added support for scalar column views in expression evaluation and JIT execution.
    • Expanded transform benchmarking to cover wide tables, configurable batch sizes, row counts, expression depth, and execution modes.
    • Added support for nested addition expression benchmarks using scalar and scalar-column inputs.

Walkthrough

The PR adds scalar column view support to AST literals and Row IR inputs. It also adds and registers a configurable wide-table transform benchmark for AST, JIT, and optimized JIT executors.

Changes

AST and JIT transform support

Layer / File(s) Summary
Literal scalar representation
cpp/include/cudf/ast/expressions.hpp
literal now stores either scalar metadata or a scalar_column_view. Accessors and validity checks dispatch between both representations.
Row IR scalar input integration
cpp/src/jit/row_ir.hpp, cpp/src/jit/row_ir.cpp
Row IR inputs now accept owned scalar columns and scalar column views. Input conversion, nullability, column extraction, and transform input assembly handle both variants.
Wide-table transform benchmark
cpp/benchmarks/transform/transform_widetable.cpp, cpp/benchmarks/CMakeLists.txt
Adds the configurable ast_jit_wide_table benchmark and includes it in the NVBench transform target.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Suggested labels: feature request

Suggested reviewers: mattgara, misiugodfrey

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 34.62% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding scalar column view support to AST expressions and JIT execution.
Description check ✅ Passed The description directly explains the scalar column view changes, JIT integration, lifetime requirement, benchmark additions, and performance results.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cpp/benchmarks/transform/transform_widetable.cpp`:
- Around line 75-76: Run clang-format on the create_sequence_table call in the
benchmark setup, ensuring the wrapped arguments align according to the project's
formatting rules. Limit the change to formatting in transform_widetable.cpp.
- Around line 21-25: Add the direct standard-library headers <utility> for
std::move and <cstddef> for std::size_t in the include section of
transform_widetable.cpp, alongside the existing headers.

In `@cpp/include/cudf/ast/expressions.hpp`:
- Around line 303-308: Update the Doxygen documentation for the
scalar_column_view constructor of literal to explicitly note that the referenced
one-row column must outlive the literal and every JIT evaluation using it,
reflecting its non-owning lifetime requirement.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 9d6a2d79-4f72-48f3-81ef-fc3b9708f791

📥 Commits

Reviewing files that changed from the base of the PR and between baea696 and 9c734e4.

📒 Files selected for processing (5)
  • cpp/benchmarks/CMakeLists.txt
  • cpp/benchmarks/transform/transform_widetable.cpp
  • cpp/include/cudf/ast/expressions.hpp
  • cpp/src/jit/row_ir.cpp
  • cpp/src/jit/row_ir.hpp

Comment thread cpp/benchmarks/transform/transform_widetable.cpp
Comment thread cpp/benchmarks/transform/transform_widetable.cpp Outdated
Comment on lines +303 to +308
/**
* @brief Construct a new literal object.
*
* @param value A scalar column view value
*/
literal(scalar_column_view value) : scalar{std::move(value)} {}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Document the non-owning lifetime requirement.

literal retains a non-owning scalar_column_view. cpp/src/jit/row_ir.cpp later forwards that view into transform_args.inputs. If the referenced column is destroyed before JIT evaluation, the transform can access invalid device memory.

Add a Doxygen note that the referenced one-row column must outlive the literal and every JIT evaluation that uses it.

Proposed documentation change
  /**
   * `@brief` Construct a new literal object.
   *
   * `@param` value A scalar column view value
+  * `@note` `value` is non-owning. The referenced one-row column must outlive this
+  * `literal` and every evaluation that uses it.
   */
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* @brief Construct a new literal object.
*
* @param value A scalar column view value
*/
literal(scalar_column_view value) : scalar{std::move(value)} {}
/**
* `@brief` Construct a new literal object.
*
* `@param` value A scalar column view value
* `@note` `value` is non-owning. The referenced one-row column must outlive this
* `literal` and every evaluation that uses it.
*/
literal(scalar_column_view value) : scalar{std::move(value)} {}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cpp/include/cudf/ast/expressions.hpp` around lines 303 - 308, Update the
Doxygen documentation for the scalar_column_view constructor of literal to
explicitly note that the referenced one-row column must outlive the literal and
every JIT evaluation using it, reflecting its non-owning lifetime requirement.

Source: Coding guidelines

@bdice bdice Aug 11, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lamarrr Can you confirm this? I don't recall the ownership model of scalar_column_view but I think this is incorrect.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the lifetime requirement for all cuDF column/scalar view types. It would be noise to re-document that at every usage site

@github-actions github-actions Bot added libcudf Affects libcudf (C++/CUDA) code. CMake CMake build issue labels Aug 10, 2026
@lamarrr lamarrr added feature request New feature or request non-breaking Non-breaking change labels Aug 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CMake CMake build issue feature request New feature or request libcudf Affects libcudf (C++/CUDA) code. non-breaking Non-breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants